package com.yixing.tech.entity.controller;

import com.yixing.tech.common.base.BaseControl;
import com.yixing.tech.common.base.BaseResponse;
import com.yixing.tech.common.base.BusinessException;
import com.yixing.tech.common.base.ConditionsVO;
import com.yixing.tech.common.base.PageRow;
import com.yixing.tech.common.base.Rs;
import com.yixing.tech.common.enums.ErrCode;
import com.yixing.tech.common.security.NoAuth;
import com.yixing.tech.common.service.CommonService;
import com.yixing.tech.common.vo.s5.EntityVO;
import com.yixing.tech.entity.entity.CustomActionParam;
import com.yixing.tech.entity.entity.GroupParam;
import com.yixing.tech.entity.po.EntityData;
import com.yixing.tech.entity.service.EntityBaseService;
import com.yixing.tech.entity.service.ICustomActuator;
import com.yixing.tech.entity.service.IEntityService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static com.yixing.tech.common.CommonConstant.CHARSET_UTF8;
import static com.yixing.tech.common.security.context.UserContext.getTenantId;
import static com.yixing.tech.common.service.CommonService.getApiUser;

/**
 * @author yixing tech
 */
@Slf4j
@RestController
@CrossOrigin
@RequestMapping(value = "/actuator")
public class ActuatorController extends BaseControl {

    @Resource
    private EntityBaseService entityBaseService;
    @Resource
    ICustomActuator customActuator;
    @Resource
    IEntityService entityService;
    @Autowired
    private CommonService commonService;

    @GetMapping("/template/{code}")
    public void getImportTemplate(HttpServletResponse response, @PathVariable String code) throws Exception {
        entityBaseService.getImportTemplate(response, code,null, commonService.getApiUser());
    }
    @GetMapping("/template/{code}/{attrCode}")
    public void getImportTemplate(HttpServletResponse response, @PathVariable String code,@PathVariable String attrCode) throws Exception {
        attrCode = attrCode.replaceAll("%(?![0-9a-fA-F]{2})", "%25");
        attrCode = URLDecoder.decode(attrCode,CHARSET_UTF8);
        entityBaseService.getImportTemplate(response, code,attrCode, commonService.getApiUser());
    }

    @PostMapping("/insert/{code}")
    public Rs<Object> insertEntity(@RequestBody LinkedHashMap map, @PathVariable String code) throws Exception {
        commonService.fillCreateUser(map);
        EntityData entity = new EntityData();
        map.remove("id");
        entity.putAll(map);
        entityService.lineConflict(code, entity);
        String id = entityBaseService.insetEntity(code, entity);
        return Rs.ok(id);
    }

    @PostMapping("/free/insert/{code}")
    public Rs<Object> insertFreeEntity(@RequestBody LinkedHashMap map, @PathVariable String code) throws Exception {
        if (!map.containsKey("tenantId")) throw new BusinessException(ErrCode.PARAMETER_ERROR);
        EntityData entity = new EntityData();
        map.remove("id");
        Date date = new Date();
        map.put("createTime", date);
        entity.putAll(map);
        String id = entityBaseService.insetEntity(code, entity);
        return Rs.ok(id);
    }

    @PostMapping("/insert/list/{code}")
    public Rs<Object> insertEntitys(@RequestBody List<Map> list, @PathVariable String code) throws Exception {
        entityBaseService.insetEntitys(code, list, commonService.getApiUser());
        return Rs.ok();
    }

    @PostMapping("/free/insert/list/{code}")
    public Rs<Object> insertFreeEntitys(@RequestBody List<Map> list, @PathVariable String code) throws Exception {
        entityBaseService.insetEntitys(code, list, null);
        return Rs.ok();
    }

    @PostMapping("/system/insert/{code}")
    public Rs<Object> systemInsertEntity(@RequestBody LinkedHashMap map, @PathVariable String code) throws Exception {
        Date date = new Date();
        map.put("createTime", date);
        map.put("updateTime", date);
        EntityData entity = new EntityData();
        entity.putAll(map);
        entityBaseService.insetEntity(code, entity);
        return Rs.ok();
    }

    @PostMapping("/import/{code}")
    public Rs<Object> importEntity(@RequestParam MultipartFile file, @PathVariable String code) throws Exception {
        entityBaseService.importEntity(code, file, commonService.getApiUser());
        return Rs.ok();
    }

    @PostMapping("/export/{code}")
    public void exportEntity(HttpServletResponse response, @PathVariable String code, @RequestBody ConditionsVO condition) throws Exception {
        condition.setTenantId(getTenantId());
        entityBaseService.exportEntity(response, code, condition, commonService.getApiUser());
    }

    @NoAuth
    @PostMapping("/listPage/{code}")
    public Rs<Object> listPage(@RequestBody PageRow<ConditionsVO> pageRow, @PathVariable String code) throws Exception {
        pageRow.getCondition(ConditionsVO.class).setTenantId(getTenantId());
        return Rs.ok(entityBaseService.listPage(pageRow, code, commonService.getApiUser()));
    }
    @PostMapping("/listPage/{code}/redundancy")
    public Rs<Object> listPageRedundancy(@RequestBody PageRow<ConditionsVO> pageRow, @PathVariable String code) throws Exception {
        pageRow.getCondition(ConditionsVO.class).setTenantId(getTenantId());
        return Rs.ok(entityBaseService.listPage(pageRow, code, commonService.getApiUser()));
    }

    @PostMapping("/listPage/{code}/simple")
    public Rs<Object> listPageSimple(@RequestBody PageRow<ConditionsVO> pageRow, @PathVariable String code) throws Exception {
        pageRow.getCondition(ConditionsVO.class).setTenantId(getTenantId());
        return Rs.ok(entityBaseService.listPageRedundancy(pageRow, code, commonService.getApiUser(),false));
    }

    @PostMapping("/list/{code}")
    public Rs<Object> list(@RequestBody ConditionsVO condition, @PathVariable String code) throws Exception {
        condition.setTenantId(getTenantId());
        return Rs.ok(entityBaseService.list(condition, code, commonService.getApiUser()));
    }

    @PostMapping("/count/{code}")
    public Rs<Object> count(@RequestBody ConditionsVO condition, @PathVariable String code) throws Exception {
        condition.setTenantId(getTenantId());
        return Rs.ok(entityBaseService.count(condition, code));
    }

    @PostMapping("/free/list/{code}")
    public Rs<Object> freeList(@RequestBody ConditionsVO condition, @PathVariable String code) throws Exception {
        return Rs.ok(entityBaseService.list(condition, code, null));
    }

    @PostMapping("/tree/{code}")
    public Rs<Object> tree(@PathVariable String code, @RequestBody ConditionsVO condition) throws Exception {
        condition.setTenantId(getTenantId());
        return Rs.ok(entityBaseService.tree(code, condition, commonService.getApiUser()));
    }

    @GetMapping("/get/{code}/{entityId}")
    public Rs<Object> getEntity(@PathVariable String entityId, @PathVariable String code) throws BusinessException {
        return Rs.ok(entityBaseService.getEntity(code, entityId, commonService.getApiUser(), true));
    }

    @GetMapping("/detail/{code}/{entityId}")
    public Rs<Object> getEntityDetail(@PathVariable String entityId, @PathVariable String code) throws BusinessException {
        return Rs.ok(entityBaseService.getEntity(code, entityId, commonService.getApiUser(), false));
    }

    @GetMapping("/free/detail/{code}/{entityId}")
    public Rs<Object> getFreeEntityDetail(@PathVariable String entityId, @PathVariable String code) throws BusinessException {
        return Rs.ok(entityBaseService.getEntity(code, entityId, null, false));
    }

    @DeleteMapping("/delete/{code}/{entityId}")
    public Rs<Object> deleteEntity(@PathVariable String entityId, @PathVariable String code) throws BusinessException {
        entityBaseService.removeEntity(code, entityId, getTenantId());
        return Rs.ok();
    }

    @DeleteMapping("/free/delete/{code}/{entityId}")
    public Rs<Object> freeDeleteEntity(@PathVariable String entityId, @PathVariable String code) throws BusinessException {
        entityBaseService.removeEntity(code, entityId, null);
        return Rs.ok();
    }

    @PostMapping("/remove/{code}")
    public Rs<Object> removeEntity(@RequestBody Map map, @PathVariable String code) throws BusinessException {
        entityBaseService.removeEntity(code, map, getTenantId());
        return Rs.ok();
    }

    @PostMapping("/removeBatch")
    public Rs<Object> removeEntities(@RequestBody Map map) throws BusinessException {
        getTenantId();
        entityBaseService.removeEntities(map.get("objId").toString(), (List<String>) map.get("ids"));
        return Rs.ok();
    }

    @PostMapping("/disable/{code}/{entityId}")
    public Rs<Object> disableEntity(@RequestBody(required = false) LinkedHashMap map, @PathVariable String code, @PathVariable String entityId) throws BusinessException {
        entityBaseService.disableEntity(code, entityId, map);
        return Rs.ok();
    }

    @PostMapping("/update/{code}/{entityId}")
    public Rs<Object> updateEntity(@RequestBody LinkedHashMap map, @PathVariable String code, @PathVariable String entityId) throws Exception {
        commonService.fillUpdateUser(map);
        EntityData entity = new EntityData();
        entity.putAll(map);
        entity.put("id", entityId);
        entityBaseService.updateEntity(code, entity);
        return Rs.ok();
    }

    @PostMapping("/update/{code}")
    public Rs<Object> updateEntity(@RequestBody EntityVO map, @PathVariable String code) throws Exception {
        Map m = map.getEntity();
        commonService.fillUpdateUser(m);
        m.put("tenantId", getTenantId());
        entityBaseService.updateEntity(code, map.getConditions(), m);
        return Rs.ok();
    }

    @PostMapping("/free/update/{code}/{entityId}")
    public Rs<Object> updateFreeEntity(@RequestBody LinkedHashMap map, @PathVariable String code, @PathVariable String entityId) throws Exception {
        EntityData entity = new EntityData();
        entity.putAll(map);
        entity.put("id", entityId);
        entityBaseService.updateEntity(code, entity);
        return Rs.ok();
    }

    @PostMapping("/customAction")
    public Rs<Object> customAction(HttpServletResponse response, @RequestBody CustomActionParam param) throws Exception {
        param.setTenantId(getTenantId());
        param.setUserVO(getApiUser());
        Object data = customActuator.customAction(response, param);
        if(data instanceof BaseResponse) {
            return Rs.ok(data);
        }
        else if (data instanceof Boolean) {
            if (!(Boolean) data) return Rs.ok();
        }
        return Rs.ok(data);
    }

    /**
     * 解析实体的excel数据
     *
     * @param file
     * @param code
     * @throws Exception
     */
    @PostMapping("/parse/excel/{code}")
    public Rs<Object> parseExcel(@RequestPart MultipartFile file,
                           @PathVariable String code) throws Exception {
        Object data = entityBaseService.parseExcel(file, code,getTenantId());
        if (data instanceof Boolean) {
            if (!(Boolean) data) return Rs.ok();
        }
        return Rs.ok(data);
    }

    /**
     * 解析实体子表单的excel数据
     *
     * @param file
     * @param code
     * @throws Exception
     */
    @PostMapping("/parse/sub/excel")
    public Rs<Object> parseSubExcel(@RequestPart("file") MultipartFile file,
                              @RequestParam("code") String code, @RequestParam("subFormAttr") String subFormAttr) throws Exception {
        return Rs.ok(entityBaseService.parseSubExcel(file, code, subFormAttr,getTenantId()));
    }

    @PostMapping("/action")
    public Rs<Object> action(@RequestBody CustomActionParam param) throws Exception {
        param.setTenantId(getTenantId());
        param.setUserVO(getApiUser());
        entityBaseService.excAction(param);
        return Rs.ok();
    }

    @PostMapping("/group")
    public Rs<Object> group(@RequestBody GroupParam param) throws Exception {
        param.setTenantId(getTenantId());
        param.setUserVO(getApiUser());
        entityBaseService.group(param);
        return Rs.ok();
    }

    @PostMapping("/count/attr/{code}")
    public Rs<Object> countAttr(@RequestBody ConditionsVO condition, @PathVariable String code) throws Exception {
        condition.setTenantId(getTenantId());
        return Rs.ok(entityBaseService.count(condition, code, condition.getAttrCode(), commonService.getApiUser()));
    }

    @PostMapping("/summation/attr/{code}")
    public Rs<Object> summationAttr(@RequestBody ConditionsVO condition, @PathVariable String code) throws Exception {
        condition.setTenantId(getTenantId());
        return Rs.ok(entityBaseService.summation(condition, code, condition.getAttrCode(), commonService.getApiUser()));
    }

//    @GetMapping("/customAction/{method}")
//    public Rs<Object> customAction(HttpServletResponse response,@PathVariable String method) throws Exception {
//        CustomActionParam param = new CustomActionParam();
//        param.setEntityId("627b7fc842211330de301de5");
//        param.setObjCode("collector");
//        param.setMethod(method);
//        param.setTenantId("e85fd66f518d495097352436c0426e23");
//        if (!customActuator.customAction(response, param))
//            return Rs.ok();
//    }
}
